```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DJL 深度学习框架指南 | 手写数字识别实战</title>
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            line-height: 1.8;
            color: #333;
        }
        .hero {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        }
        .code-block {
            background: #282c34;
            border-radius: 8px;
            box-shadow: 0 10px 20px rgba(0,0,0,0.1);
        }
        .card {
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 15px 30px rgba(0,0,0,0.15);
        }
        .highlight {
            background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(245, 158, 11, 0.1) 100%);
            border-left: 4px solid #f59e0b;
        }
        h1, h2, h3, h4, h5, h6 {
            font-family: 'Noto Serif SC', serif;
            font-weight: 600;
        }
        .first-letter:first-letter {
            font-size: 3em;
            float: left;
            line-height: 0.8;
            margin-right: 8px;
            color: #667eea;
            font-weight: bold;
        }
    </style>
</head>
<body class="bg-gray-50">
    <!-- Hero Section -->
    <section class="hero text-white py-20 px-4 sm:px-6 lg:px-8">
        <div class="max-w-6xl mx-auto">
            <div class="flex flex-col md:flex-row items-center">
                <div class="md:w-1/2 mb-10 md:mb-0">
                    <h1 class="text-4xl md:text-5xl font-bold mb-4">DJL 深度学习框架</h1>
                    <p class="text-xl md:text-2xl opacity-90 mb-8">基于Java生态的高性能AI开发解决方案</p>
                    <p class="text-lg opacity-80 mb-8">一个易用、高性能的深度学习框架，支持多种主流引擎（如PyTorch、TensorFlow等），完全基于Java生态，让您无需切换编程语言即可构建AI应用。</p>
                    <div class="flex space-x-4">
                        <a href="#overview" class="bg-white text-indigo-700 px-6 py-3 rounded-lg font-medium hover:bg-gray-100 transition duration-300">
                            <i class="fas fa-book mr-2"></i>了解详情
                        </a>
                        <a href="#code" class="bg-indigo-800 text-white px-6 py-3 rounded-lg font-medium hover:bg-indigo-900 transition duration-300">
                            <i class="fas fa-code mr-2"></i>查看代码
                        </a>
                    </div>
                </div>
                <div class="md:w-1/2 flex justify-center">
                    <div class="relative w-full max-w-md">
                        <div class="absolute -top-6 -left-6 w-64 h-64 bg-purple-300 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob"></div>
                        <div class="absolute -bottom-8 -right-8 w-64 h-64 bg-yellow-300 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-2000"></div>
                        <div class="absolute top-20 -right-10 w-64 h-64 bg-pink-300 rounded-full mix-blend-multiply filter blur-xl opacity-70 animate-blob animation-delay-4000"></div>
                        <div class="relative">
                            <img src="https://cdn.nlark.com/yuque/0/2024/png/21449790/1734167379098-46b3750f-ed2c-4d87-ab40-8d438c47c48e.png" alt="MNIST手写数字识别示例" class="rounded-lg shadow-2xl border-4 border-white">
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Overview Section -->
    <section id="overview" class="py-16 px-4 sm:px-6 lg:px-8">
        <div class="max-w-6xl mx-auto">
            <div class="text-center mb-16">
                <h2 class="text-3xl font-bold mb-4 text-gray-800">MNIST 手写数字识别实战</h2>
                <p class="text-xl text-gray-600 max-w-3xl mx-auto">使用DJL构建一个简单的多层感知机(MLP)模型，实现经典的手写数字识别任务</p>
            </div>

            <div class="grid grid-cols-1 md:grid-cols-3 gap-8 mb-16">
                <div class="card bg-white p-6 rounded-xl shadow-lg">
                    <div class="text-indigo-600 text-4xl mb-4">
                        <i class="fas fa-database"></i>
                    </div>
                    <h3 class="text-xl font-bold mb-3 text-gray-800">数据集加载</h3>
                    <p class="text-gray-600">使用DJL内置的MNIST数据集加载器，轻松获取训练和测试数据，内置进度条显示加载进度。</p>
                </div>
                <div class="card bg-white p-6 rounded-xl shadow-lg">
                    <div class="text-indigo-600 text-4xl mb-4">
                        <i class="fas fa-project-diagram"></i>
                    </div>
                    <h3 class="text-xl font-bold mb-3 text-gray-800">模型构建</h3>
                    <p class="text-gray-600">简单的多层感知机(MLP)架构，包含输入层(784节点)、两个隐藏层(128和64节点)和输出层(10节点)。</p>
                </div>
                <div class="card bg-white p-6 rounded-xl shadow-lg">
                    <div class="text-indigo-600 text-4xl mb-4">
                        <i class="fas fa-cogs"></i>
                    </div>
                    <h3 class="text-xl font-bold mb-3 text-gray-800">训练与评估</h3>
                    <p class="text-gray-600">配置交叉熵损失函数和准确率评估器，使用EasyTrain进行5个epoch的训练，并保存模型。</p>
                </div>
            </div>

            <div class="mb-16">
                <h3 class="text-2xl font-bold mb-6 text-gray-800 border-b pb-2">技术架构概述</h3>
                <div class="bg-white rounded-xl shadow-lg p-6">
                    <div class="mermaid">
                        graph LR
                            A[MNIST数据集] --> B[数据预处理]
                            B --> C[多层感知机模型]
                            C --> D[训练配置]
                            D --> E[模型训练]
                            E --> F[模型评估]
                            F --> G[模型保存]
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Code Section -->
    <section id="code" class="py-16 px-4 sm:px-6 lg:px-8 bg-gray-100">
        <div class="max-w-6xl mx-auto">
            <div class="text-center mb-16">
                <h2 class="text-3xl font-bold mb-4 text-gray-800">代码详解</h2>
                <p class="text-xl text-gray-600 max-w-3xl mx-auto">实现手写数字识别的完整代码解析</p>
            </div>

            <div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-12">
                <div>
                    <h3 class="text-2xl font-bold mb-6 text-gray-800">1. 数据集加载</h3>
                    <p class="mb-6 first-letter">数据是深度学习的基础。MNIST是一个经典的手写数字数据集，每张图片为28×28像素的灰度图像。我们使用DJL提供的Mnist类来加载数据集。</p>
                    
                    <div class="code-block p-4 mb-6">
                        <pre class="text-gray-200"><code>private RandomAccessDataset getDataset(Dataset.Usage usage) throws Exception {
    Mnist mnist = Mnist.builder()
            .optUsage(usage) // 指定数据用途：训练（TRAIN）或测试（TEST）
            .setSampling(64, true) // 设置批量大小为64，随机抽样
            .build();
    mnist.prepare(new ProgressBar()); // 准备数据并显示加载进度条
    return mnist; // 返回加载好的数据集
}</code></pre>
                    </div>
                    
                    <div class="bg-white p-4 rounded-lg shadow-sm mb-6 highlight">
                        <h4 class="font-bold text-gray-800 mb-2 flex items-center">
                            <i class="fas fa-lightbulb text-yellow-500 mr-2"></i>关键点
                        </h4>
                        <ul class="list-disc pl-5 text-gray-700">
                            <li><code>RandomAccessDataset</code> 是 DJL 提供的接口，用于表示可以按索引访问的数据集</li>
                            <li><code>setSampling(64, true)</code> 设置每次从数据集中随机抽取64条数据</li>
                            <li><code>ProgressBar</code> 是一个简单的加载进度条，方便监控数据加载进度</li>
                        </ul>
                    </div>
                </div>

                <div>
                    <h3 class="text-2xl font-bold mb-6 text-gray-800">2. 定义模型</h3>
                    <p class="mb-6 first-letter">我们使用多层感知机（MLP）模型。MLP是一种经典的全连接神经网络，由输入层、若干隐藏层和输出层组成。</p>
                    
                    <div class="code-block p-4 mb-6">
                        <pre class="text-gray-200"><code>Block block = new Mlp(28 * 28, 10, new int[]{128, 64});</code></pre>
                    </div>
                    
                    <div class="bg-white p-4 rounded-lg shadow-sm mb-6">
                        <h4 class="font-bold text-gray-800 mb-2">参数说明</h4>
                        <table class="min-w-full divide-y divide-gray-200">
                            <tbody class="bg-white divide-y divide-gray-200">
                                <tr>
                                    <td class="px-4 py-2 whitespace-nowrap font-medium text-gray-900">28 * 28</td>
                                    <td class="px-4 py-2 whitespace-nowrap text-gray-700">输入层的大小（MNIST图片的像素数）</td>
                                </tr>
                                <tr>
                                    <td class="px-4 py-2 whitespace-nowrap font-medium text-gray-900">10</td>
                                    <td class="px-4 py-2 whitespace-nowrap text-gray-700">输出层的大小（10类数字：0-9）</td>
                                </tr>
                                <tr>
                                    <td class="px-4 py-2 whitespace-nowrap font-medium text-gray-900">{128, 64}</td>
                                    <td class="px-4 py-2 whitespace-nowrap text-gray-700">两个隐藏层的神经元数量</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                    
                    <p class="mb-6">MLP的工作原理是：输入数据经过每层神经元的加权计算（权重 + 偏置），再通过激活函数非线性变换，逐步提取数据的特征。</p>
                </div>
            </div>

            <div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-12">
                <div>
                    <h3 class="text-2xl font-bold mb-6 text-gray-800">3. 配置训练流程</h3>
                    <p class="mb-6 first-letter">训练神经网络需要配置损失函数、评估指标和监听器。DJL提供了简单易用的API来配置这些训练参数。</p>
                    
                    <div class="code-block p-4 mb-6">
                        <pre class="text-gray-200"><code>DefaultTrainingConfig config = new DefaultTrainingConfig(Loss.softmaxCrossEntropyLoss()) // 使用交叉熵损失
        .addEvaluator(new Accuracy()) // 添加准确率评估器
        .addTrainingListeners(TrainingListener.Defaults.logging(outDir)); // 添加日志监听器</code></pre>
                    </div>
                    
                    <div class="bg-white p-4 rounded-lg shadow-sm mb-6">
                        <h4 class="font-bold text-gray-800 mb-2">配置项说明</h4>
                        <table class="min-w-full divide-y divide-gray-200">
                            <tbody class="bg-white divide-y divide-gray-200">
                                <tr>
                                    <td class="px-4 py-2 whitespace-nowrap font-medium text-gray-900">Loss.softmaxCrossEntropyLoss()</td>
                                    <td class="px-4 py-2 whitespace-nowrap text-gray-700">分类任务的常用损失函数</td>
                                </tr>
                                <tr>
                                    <td class="px-4 py-2 whitespace-nowrap font-medium text-gray-900">Accuracy()</td>
                                    <td class="px-4 py-2 whitespace-nowrap text-gray-700">评估模型分类准确率</td>
                                </tr>
                                <tr>
                                    <td class="px-4 py-2 whitespace-nowrap font-medium text-gray-900">TrainingListener.Defaults.logging()</td>
                                    <td class="px-4 py-2 whitespace-nowrap text-gray-700">训练过程日志记录</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>

                <div>
                    <h3 class="text-2xl font-bold mb-6 text-gray-800">4. 开始训练</h3>
                    <p class="mb-6 first-letter">训练流程包括初始化模型、迭代训练数据集和验证集，并记录结果。DJL的EasyTrain提供了简化的训练方法。</p>
                    
                    <div class="code-block p-4 mb-6">
                        <pre class="text-gray-200"><code>try (Trainer trainer = model.newTrainer(config)) {
    trainer.setMetrics(new Metrics()); // 设置指标收集器
    trainer.initialize(new Shape(1, Mnist.IMAGE_HEIGHT * Mnist.IMAGE_WIDTH)); // 初始化模型输入的形状
    EasyTrain.fit(trainer, 5, trainingSet, validateSet); // 开始训练，5个周期（epoch）
}</code></pre>
                    </div>
                    
                    <div class="bg-white p-4 rounded-lg shadow-sm mb-6 highlight">
                        <h4 class="font-bold text-gray-800 mb-2 flex items-center">
                            <i class="fas fa-info-circle text-blue-500 mr-2"></i>训练说明
                        </h4>
                        <ul class="list-disc pl-5 text-gray-700">
                            <li><code>EasyTrain.fit</code>：DJL提供的简化训练方法，自动完成训练、验证和评估</li>
                            <li><code>trainer.setMetrics</code>：记录训练过程中的损失值和评估指标</li>
                            <li>5个epoch表示整个数据集将被遍历5次进行训练</li>
                        </ul>
                    </div>
                </div>
            </div>

            <div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-12">
                <div>
                    <h3 class="text-2xl font-bold mb-6 text-gray-800">5. 保存模型</h3>
                    <p class="mb-6 first-letter">训练完成后，保存模型以供后续使用。DJL提供了简单的模型保存方法，会将模型结构和参数一起保存。</p>
                    
                    <div class="code-block p-4 mb-6">
                        <pre class="text-gray-200"><code>Path modelDir = Paths.get("build/mlp");
model.save(modelDir, "mlp");</code></pre>
                    </div>
                    
                    <div class="bg-white p-4 rounded-lg shadow-sm mb-6">
                        <p class="text-gray-700"><code>model.save</code> 将训练好的模型保存到指定路径（<code>build/mlp</code>），包括模型的结构、参数和训练周期数等元信息。</p>
                    </div>
                </div>

                <div>
                    <h3 class="text-2xl font-bold mb-6 text-gray-800">6. 完整代码示例</h3>
                    <p class="mb-6 first-letter">以下是完整的训练代码，展示了如何使用DJL从数据加载到模型训练的完整流程。</p>
                    
                    <div class="code-block p-4 mb-6">
                        <pre class="text-gray-200"><code>@Test
public void testCreateModel() throws Exception {
    // 获取训练集和测试集
    RandomAccessDataset trainingSet = getDataset(Dataset.Usage.TRAIN);
    RandomAccessDataset validateSet = getDataset(Dataset.Usage.TEST);

    // 定义模型结构
    Block block = new Mlp(28 * 28, 10, new int[]{128, 64});

    try (Model model = Model.newInstance("mlp")) {
        model.setBlock(block);

        String outDir = "build/mlp";
        DefaultTrainingConfig config = new DefaultTrainingConfig(Loss.softmaxCrossEntropyLoss())
                .addEvaluator(new Accuracy())
                .addTrainingListeners(TrainingListener.Defaults.logging(outDir));

        try (Trainer trainer = model.newTrainer(config)) {
            trainer.setMetrics(new Metrics());
            trainer.initialize(new Shape(1, Mnist.IMAGE_HEIGHT * Mnist.IMAGE_WIDTH));
            EasyTrain.fit(trainer, 5, trainingSet, validateSet);

            TrainingResult result = trainer.getTrainingResult();
            System.out.println("result = " + result);

            Path modelDir = Paths.get("build/mlp");
            model.save(modelDir, "mlp");
        }
    }
}</code></pre>
                    </div>
                </div>
            </div>

            <div class="mb-12">
                <h3 class="text-2xl font-bold mb-6 text-gray-800">POM依赖配置</h3>
                <p class="mb-6 first-letter">使用DJL需要添加相应的Maven依赖。以下是本项目中使用的关键依赖配置。</p>
                
                <div class="code-block p-4 mb-6">
                    <pre class="text-gray-200"><code>&lt;properties&gt;
    &lt;java.version&gt;17&lt;/java.version&gt;
    &lt;djl.version&gt;0.26.0&lt;/djl.version&gt;
&lt;/properties&gt;
&lt;dependencies&gt;
    &lt;!-- 引入djl依赖 --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;ai.djl&lt;/groupId&gt;
        &lt;artifactId&gt;api&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;ai.djl&lt;/groupId&gt;
        &lt;artifactId&gt;basicdataset&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;ai.djl&lt;/groupId&gt;
        &lt;artifactId&gt;model-zoo&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;ai.djl.mxnet&lt;/groupId&gt;
        &lt;artifactId&gt;mxnet-engine&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;ai.djl.mxnet&lt;/groupId&gt;
        &lt;artifactId&gt;mxnet-native-auto&lt;/artifactId&gt;
        &lt;version&gt;1.8.0&lt;/version&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;dependencyManagement&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;ai.djl&lt;/groupId&gt;
            &lt;artifactId&gt;bom&lt;/artifactId&gt;
            &lt;version&gt;${djl.version}&lt;/version&gt;
            &lt;type&gt;pom&lt;/type&gt;
            &lt;scope&gt;import&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/dependencyManagement&gt;</code></pre>
                </div>
            </div>
        </div>
    </section>

    <!-- Result Section -->
    <section class="py-16 px-4 sm:px-6 lg:px-8 bg-white">
        <div class="max-w-6xl mx-auto">
            <div class="text-center mb-16">
                <h2 class="text-3xl font-bold mb-4 text-gray-800">模型输出示例</h2>
                <p class="text-xl text-gray-600 max-w-3xl mx-auto">训练完成后模型的预测结果展示</p>
            </div>

            <div class="flex flex-col md:flex-row items-center justify-center">
                <div class="md:w-1/2 mb-8 md:mb-0">
                    <img src="https://cdn.nlark.com/yuque/0/2024/png/21449790/1734167379098-46b3750f-ed2c-4d87-ab40-8d438c47c48e.png" alt="MNIST手写数字识别结果" class="rounded-lg shadow-xl border border-gray-200">
                </div>
                <div class="md:w-1/2 md:pl-12">
                    <h3 class="text-2xl font-bold mb-4 text-gray-800">预测结果分析</h3>
                    <p class="mb-6">上图展示了模型对手写数字"8"的预测结果。模型以99.9%的置信度正确识别了这个数字。</p>
                    
                    <div class="bg-gray-100 p-4 rounded-lg">
                        <h4 class="font-bold text-gray-800 mb-2">预测流程说明：</h4>
                        <ol class="list-decimal pl-5 text-gray-700 space-y-2">
                            <li>从本地文件加载待预测的图片</li>
                            <li>使用<code>ImageFactory</code>将图片转换为模型可处理的格式</li>
                            <li>加载训练好的MLP模型</li>
                            <li>创建<code>Translator</code>处理输入图像(调整为28x28大小并转化为张量)</li>
                            <li>使用<code>Predictor</code>进行预测</li>
                            <li>输出分类结果和对应的置信度</li>
                        </ol>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Footer -->
    <footer class="bg-gray-900 text-white py-12 px-4 sm:px-6 lg:px-8">
        <div class="max-w-6xl mx-auto">
            <div class="flex flex-col items-center">
                <div class="mb-6">
                    <h3 class="text-2xl font-bold">技术小馆</h3>
                </div>
                <div class="mb-6">
                    <a href="http://www.yuque.com/jtostring" class="text-gray-300 hover:text-white transition duration-300">
                        <i class="fas fa-globe mr-2"></i>http://www.yuque.com/jtostring
                    </a>
                </div>
                <div class="flex space-x-6">
                    <a href="#" class="text-gray-300 hover:text-white transition duration-300">
                        <i class="fab fa-github text-xl"></i>
                    </a>
                    <a href="#" class="text-gray-300 hover:text-white transition duration-300">
                        <i class="fab fa-twitter text-xl"></i>
                    </a>
                    <a href="#" class="text-gray-300 hover:text-white transition duration-300">
                        <i class="fab fa-youtube text-xl"></i>
                    </a>
                </div>
            </div>
        </div>
    </footer>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis'
            }
        });
    </script>
</body>
</html>
```